<template>
	<view :class="{ 'camera-page': true, 'safety-zone-bottom': phoneSafeArea }" :style="`--theme-color: ${color}`">
		<canvas v-if="canvasH" class="camera-canvas" canvas-id="myCanvas"
			:style="{ width: canvasW + 'px', height: canvasH + 'px' }"></canvas>

		<view v-show="!cameraSrc">
			<camera :class="{'camera-box-vin':type === 'vin', 'camera-box-plate':type === 'plate'}" mode="normal"
				:device-position="devicePosition" resolution="high" frame-size="medium" output-dimension="max"
				flash="off" @error="onChangeError">
				<!-- 取景框 -->
				<cover-view class="camera-aperture" id="frameDom"></cover-view>
				<cover-view class="camera-aperture-line camera-aperture-top"></cover-view>
				<cover-view class="camera-aperture-line camera-aperture-right"></cover-view>
				<cover-view class="camera-aperture-line camera-aperture-bottom"></cover-view>
				<cover-view class="camera-aperture-line camera-aperture-left"></cover-view>
				<cover-view v-if="tipsText" class="camera-aperture-tips">{{ tipsText }}</cover-view>
			</camera>

			<!-- 操作栏 -->
			<view class="camera-control">
				<view class="left-item">
					<text class="txt" @click="cancel">取消</text>
				</view>
				<view class="center-item">
					<view class="photo-btn" @click="takePhoto">
						<view class="photo"></view>
					</view>
				</view>
				<view class="right-item">
					<image class="device-pos" src="../../commons/images/翻转镜头.svg" @click="onDevicePosition" />
				</view>
			</view>
		</view>

		<!-- 图片预览 -->
		<view v-show="cameraSrc" class="camera-img">
			<view class="preview-box">
				<image class="preview" :src="cameraSrc" mode="widthFix" />
			</view>
			<view class="preview-edit">
				<view class="preview-edit-btn" @click="onCancel">取消</view>
				<view class="preview-edit-btn submit-btn" @click="onConfirm">确认</view>
			</view>
		</view>

		<!-- 安全区 -->
		<view v-if="phoneSafeArea" class="safety-zone"></view>
	</view>
</template>

<script>
	export default {
		props: {
			// 提示语句
			tipsText: {
				type: String,
				default: '请靠近取景框'
			},

			// 颜色
			color: {
				type: String,
				default: '#6074C1'
			},

			//拍摄类型
			type: {
				type: String,
				default: "vin"
			}
		},

		data() {
			return {
				devicePosition: 'back', // 默认前置
				cameraSrc: '',
				canvasW: 0,
				canvasH: 0,
				pageWidth: 0,
				frameOptions: {}, // 取景框配置信息
				phoneSafeArea: false // 设备安全区
			}
		},

		mounted() {
			uni.getSystemInfo({
				success: res => {
					// 安全区判断
					if (res.safeAreaInsets.bottom) this.phoneSafeArea = true
				}
			})

			this.$nextTick(() => {
				const query = uni.createSelectorQuery().in(this)
				query
					.select('#frameDom')
					.boundingClientRect(data => {
						this.frameOptions = data
						console.log('得到布局位置信息' + JSON.stringify(data))
					})
					.exec()

				// 系统信息
				const winInfo = uni.getSystemInfoSync()
				this.pageWidth = winInfo.windowWidth
			})
		},

		methods: {
			// 取消预览
			onCancel() {
				this.cameraSrc = ''
			},

			//取消拍摄
			cancel() {
				this.$emit('cancel'); // 发射 cancel 事件
			},

			// 确认照片
			onConfirm() {
				this.$emit('onConfirm', {
					url: this.cameraSrc
				})
			},

			// 拍照
			takePhoto() {
				const ctx = uni.createCameraContext()
				ctx.takePhoto({
					quality: 'high',
					selfieMirror: true, // 是否开启镜像 默认true
					success: async res => {
						this.cameraSrc = await this.cropImage(res.tempImagePath)
					},
					fail: () => {
						uni.showToast({
							title: '拍照失败，请重试',
							icon: 'none'
						})
					}
				})
			},

			// 裁剪图片
			cropImage(imgUrl) {
				return new Promise((resolve, reject) => {
					uni.getImageInfo({
						src: imgUrl,
						success: file => {
							// 取景框信息
							const options = {
								width: this.frameOptions.width,
								height: this.frameOptions.height,
								y: this.frameOptions.top,
								x: this.frameOptions.left
							}

							const ctx = uni.createCanvasContext('myCanvas', this)

							const proportion = file.width / this.pageWidth
							this.canvasW = file.width / proportion
							this.canvasH = file.height / proportion

							// 绘制图片到canvas，这里可以根据需要裁剪图片
							ctx.drawImage(file.path, 0, 0, this.canvasW, this.canvasH)
							// console.log('drawImage 完成', options)

							// 导出canvas为图片
							ctx.draw(true, () => {
								console.log('canvasToTempFilePath')
								setTimeout(() => {
									// canvas 转 图片
									uni.canvasToTempFilePath({
											x: options.x,
											y: options.y,
											width: options.width,
											height: options.height,
											destWidth: options.width,
											destHeight: options.height,
											canvasId: 'myCanvas',
											fileType: 'jpg',
											quality: 1,
											success: res => {
												resolve(res.tempFilePath)
											},
											fail(err) {
												reject(err)
											}
										},
										this
									)
								}, 500)
							})
						},
						fail(err) {
							reject(err)
						}
					})
				})
			},

			// 保存图片到手机相册
			saveImageToPhone(filePath) {
				uni.saveImageToPhotosAlbum({
					filePath,
					success: () => {
						uni.showToast({
							icon: 'none',
							title: '拍照成功'
						})
					}
				})
			},

			// 切换摄像头
			onDevicePosition() {
				this.devicePosition = this.devicePosition == 'front' ? 'back' : 'front'
			},

			// 监听报错
			onChangeError(e) {
				console.error('camera报错：', e.detail)
			}
		}
	}
</script>

<style lang="scss" scoped>
	.camera-page {
		--control-h: 200rpx;

		position: fixed;
		top: 0;
		left: 0;
		z-index: 99;
		width: 100vw;
		height: 100vh;
		overflow: hidden;
		background-color: #fff;

		.camera-box-vin {
			--aperture-t: 30vh;
			--aperture-w: 740rpx;
			--aperture-h: 120rpx;
			--aperture-line: 4rpx;
			--aperture-line-style: 4rpx dashed #fff;
			--edit-padding: 64rpx;

			position: relative;
			width: 100vw;
			height: calc(100vh - var(--control-h));

			.camera-aperture {
				position: absolute;
				top: var(--aperture-t);
				left: 0;
				right: 0;
				width: var(--aperture-w);
				height: var(--aperture-h);
				border-style: dashed;
				border-width: 4rpx;
				border-color: #f9f9f9;
				margin: 0 auto;
				pointer-events: none;
				opacity: 0;
			}

			.camera-aperture-line {
				position: absolute;
				background-color: #fff;
				z-index: 2;
			}

			.camera-aperture-top {
				top: var(--aperture-t);
				left: calc((100vw - var(--aperture-w)) / 2);
				width: var(--aperture-w);
				height: var(--aperture-line);
			}

			.camera-aperture-right {
				top: var(--aperture-t);
				left: calc(var(--aperture-w) + (100vw - var(--aperture-w)) / 2);
				width: var(--aperture-line);
				height: var(--aperture-h);
			}

			.camera-aperture-bottom {
				top: calc(var(--aperture-t) + var(--aperture-h));
				left: calc((100vw - var(--aperture-w)) / 2);
				width: calc(var(--aperture-w) + var(--aperture-line));
				height: var(--aperture-line);
			}

			.camera-aperture-left {
				top: var(--aperture-t);
				left: calc((100vw - var(--aperture-w)) / 2);
				width: var(--aperture-line);
				height: var(--aperture-h);
			}

			.camera-aperture-tips {
				position: absolute;
				top: calc(var(--aperture-t) + 180rpx);
				left: 0;
				right: 0;
				font-size: 32rpx;
				color: #fff;
				max-width: 95%;
				color: #fff;
				text-align: center;
				margin: 0 auto;
			}
		}


		.camera-box-plate {
			--aperture-t: 30vh;
			--aperture-w: 700rpx;
			--aperture-h: 230rpx;
			--aperture-line: 4rpx;
			--aperture-line-style: 4rpx dashed #fff;
			--edit-padding: 64rpx;

			position: relative;
			width: 100vw;
			height: calc(100vh - var(--control-h));

			.camera-aperture {
				position: absolute;
				top: var(--aperture-t);
				left: 0;
				right: 0;
				width: var(--aperture-w);
				height: var(--aperture-h);
				border-style: dashed;
				border-width: 4rpx;
				border-color: #f9f9f9;
				margin: 0 auto;
				pointer-events: none;
				opacity: 0;
			}

			.camera-aperture-line {
				position: absolute;
				background-color: #fff;
				z-index: 2;
			}

			.camera-aperture-top {
				top: var(--aperture-t);
				left: calc((100vw - var(--aperture-w)) / 2);
				width: var(--aperture-w);
				height: var(--aperture-line);
			}

			.camera-aperture-right {
				top: var(--aperture-t);
				left: calc(var(--aperture-w) + (100vw - var(--aperture-w)) / 2);
				width: var(--aperture-line);
				height: var(--aperture-h);
			}

			.camera-aperture-bottom {
				top: calc(var(--aperture-t) + var(--aperture-h));
				left: calc((100vw - var(--aperture-w)) / 2);
				width: calc(var(--aperture-w) + var(--aperture-line));
				height: var(--aperture-line);
			}

			.camera-aperture-left {
				top: var(--aperture-t);
				left: calc((100vw - var(--aperture-w)) / 2);
				width: var(--aperture-line);
				height: var(--aperture-h);
			}

			.camera-aperture-tips {
				position: absolute;
				top: calc(var(--aperture-t) + 250rpx);
				left: 0;
				right: 0;
				font-size: 32rpx;
				color: #fff;
				max-width: 95%;
				color: #fff;
				text-align: center;
				margin: 0 auto;
			}
		}


		.camera-control {
			width: 100%;
			height: var(--control-h);
			background-color: #fff;
			padding: 0 56rpx;
			box-sizing: border-box;
			display: flex;
			align-items: center;
			justify-content: space-between;

			.left-item {
				width: 25%;
				display: flex;

				.txt {
					font-size: 32rpx;
					color: var(--theme-color);
				}
			}

			.center-item {
				width: 50%;
				display: flex;
				align-items: center;

				.photo-btn {
					width: 140rpx;
					height: 140rpx;
					border: 4rpx solid var(--theme-color);
					border-radius: 50%;
					padding: 10rpx;
					box-sizing: border-box;
					margin: 0 auto;

					.photo {
						width: 100%;
						height: 100%;
						border-radius: 50%;
						background-color: var(--theme-color);
					}
				}
			}

			.right-item {
				width: 25%;
				display: flex;
				justify-content: flex-end;

				.device-pos {
					width: 66rpx;
					height: 66rpx;
				}
			}
		}

		.camera-img {
			position: relative;
			width: 100vw;
			z-index: 9999;

			.preview-box {
				width: 100%;
				height: calc(100vh - var(--control-h));
				background-color: #f5f5f5;
				display: flex;
				align-items: center;
				justify-content: center;

				.preview {
					width: 100%;
					height: 100%;
				}
			}

			.preview-edit {
				width: 100%;
				height: var(--control-h);
				display: flex;
				justify-content: space-between;
				align-items: center;
				padding: 0 60rpx;
				box-sizing: border-box;
				background-color: #fff;
				// box-shadow: 0 -4rpx 12rpx rgba(158, 158, 158, 0.05);
				z-index: 9;

				.preview-edit-btn {
					padding: 16rpx 36rpx;
					border-radius: 12rpx;
					background-color: #fff;
					font-size: 32rpx;
					line-height: 1;
					color: #565656;
					font-weight: bold;
				}

				.submit-btn {
					// background-color: var(--theme-color);
					// color: #fff;
					color: var(--theme-color);
				}
			}
		}

		.camera-canvas {
			position: fixed;
			top: 200vh;
			left: 0;
			z-index: -999;
			opacity: 0;
		}
	}

	// 安全底部
	.safety-zone-bottom {
		--safety-zone-bottom: 34px;

		.camera-img>.preview-box,
		.camera-box {
			height: calc(100vh - var(--control-h) - var(--safety-zone-bottom));
		}

		.safety-zone {
			height: var(--safety-zone-bottom);
			width: 100%;
			background-color: inherit;
			z-index: 9999;
		}
	}
</style>